﻿Imports Configuration.Templating.Resource
Imports Configuration.Templating.Scope
Imports Configuration.Templating.Context
Imports Configuration.Templating.Default
Imports System.Reflection

Namespace Configuration.Templating

    Public Class TemplateProvider

        Public Shared m_Usage As TemplateProvider = Nothing
        Public Shared ReadOnly Property Usage As TemplateProvider
            Get
                If (m_Usage Is Nothing) Then
                    Dim Path As String = System.IO.Path.Combine(DotNetNuke.Common.Globals.ApplicationMapPath, "DesktopModules/Aricie.LuceneSearch/Resources")
                    If Not System.IO.Directory.Exists(Path) Then
                        System.IO.Directory.CreateDirectory(Path)
                    End If
                    m_Usage = New TemplateProvider(Path)
                End If
                Return m_Usage
            End Get
        End Property

        Private Property ModulePath As String
        Private Property Resources As New Dictionary(Of String, IInternalResourceHandler)

        Public Property DefaultProvider As IDefaultTemplateProvider = New DefaultTemplateProvider 'TODO: brancher sur IOC
        Public Property NameResolver As Func(Of String, String) = New Func(Of String, String)(Function(key As String) "LuceneSearch.Templates." & key & ".resx")
        Public Property IInternalResourceHandlerFactory As Func(Of String, IInternalResourceHandler) = New Func(Of String, IInternalResourceHandler)(Function(resourceKey As String) New ResxResourceHandler(System.IO.Path.Combine(ModulePath, NameResolver(resourceKey))))

        Public Sub New(ModuleSourcePath As String)
            ModulePath = ModuleSourcePath

        End Sub

        Public Function ValueExists(Scope As ITemplateProviderScope, Context As ITemplatingContext) As Boolean
            Return GetResource(Scope.RetrieveNaming())(Context.Key) IsNot Nothing
        End Function

        Public Function GetValue(Scope As ITemplateProviderScope, Context As ITemplatingContext) As String
            Dim value As String = Nothing
            Dim currentKey As String = String.Empty
            While value Is Nothing AndAlso Context IsNot Nothing
                Dim workingScope = Scope
                While value Is Nothing AndAlso workingScope IsNot Nothing
                    currentKey = Context.Key
                    value = GetResource(workingScope.RetrieveNaming())(currentKey)
                    workingScope = workingScope.RetrieveParentScope()
                End While
                Context = Context.GetParentContext()
            End While
            If value Is Nothing AndAlso DefaultProvider IsNot Nothing Then
                Return DefaultProvider.GetDefaultTemplate(currentKey)
            End If
            Return value
        End Function

        Public Sub DeleteValue(Scope As ITemplateProviderScope, Context As ITemplatingContext)
            GetResource(Scope.RetrieveNaming()).DeleteKey(Context.Key)
        End Sub

        Public Sub SetValue(Scope As ITemplateProviderScope, Context As ITemplatingContext, Value As String)
            GetResource(Scope.RetrieveNaming())(Context.Key) = Value
        End Sub

        Private Function GetResource(resourceKey As String) As IInternalResourceHandler
            If Not Resources.ContainsKey(resourceKey) Then
                Resources.Add(resourceKey, IInternalResourceHandlerFactory(resourceKey))
            End If
            Return Resources(resourceKey)
        End Function

        Public Sub Reload()
            Resources.Clear()
        End Sub

        Public Sub CommitAll()
            For Each r In Resources
                r.Value.CommitChanges()
            Next
        End Sub

        Public Shared Function FromSession(Session As IHttpSessionState) As TemplateProvider
            If (Session("CurrentTemplateProvider") Is Nothing) Then
                Session("CurrentTemplateProvider") = Usage.Clone()
            End If
            Return DirectCast(Session("CurrentTemplateProvider"), TemplateProvider)
        End Function

        Public Function Clone() As TemplateProvider
            Return New TemplateProvider(ModulePath)
        End Function

        Public Sub OverrideCurrent()
            m_Usage = Me
        End Sub

        Public ReadOnly Property SerializableResource(Scope As ITemplateProviderScope) As ISerializableResourceHandler
            Get
                Return DirectCast(GetResource(Scope.RetrieveNaming()), ISerializableResourceHandler)
            End Get
        End Property

    End Class
End Namespace